/**
 * 
 */
package org.abettor.smartswt;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;

import org.abettor.smartswt.factory.ShellFactory;
import org.abettor.smartswt.factory.SingletonDisplayFactory;
import org.abettor.smartswt.factory.WidgetFactory;
import org.abettor.smartswt.factory.WidgetListenerProxy;
import org.abettor.smartswt.factory.WidgetPropertyParametersProxy;
import org.abettor.smartswt.global.SingletonGlobalInfo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;

/**
 * 用来遍历配置文件，生成主界面及其组件
 * @author abettor
 *
 */
public class ConfigurationTraveller
{
	//	配置文件信息
	private Configuration conf = null;
	//	配置文件的根节点信息
	private Element rootElement = null;
	//	主界面对象
	private Shell shell = null;

	/**
	 * 构造函数
	 * @param conf 配置文件
	 */
	public ConfigurationTraveller(Configuration conf)
	{
		this.conf = conf;

		SAXReader saxReader = new SAXReader();
		try
		{
			Document domDoc = saxReader.read(conf.getConfigurationFile());
			rootElement = domDoc.getRootElement();
		}
		catch(DocumentException e)
		{
			e.printStackTrace();
			return;
		}
	}

	/**
	 * 获取配置文件信息
	 * @return 返回配置文件信息
	 */
	public Configuration getConfiguration()
	{
		return conf;
	}

	/**
	 * 遍历配置文件，生成主界面及其子组件<br />
	 * 默认遍历名称为“main”的主界面
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws NoSuchMethodException 
	 * @throws ClassNotFoundException 
	 * @throws NoSuchFieldException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 */
	public void travel()
	throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchFieldException
	{
		travel("main", null);
	}

	/**
	 * 遍历配置文件，生成主界面及其子组件
	 * @param shellName 要遍历的主界面名称
	 * @param parentShell 父窗口的引用
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws NoSuchMethodException 
	 * @throws ClassNotFoundException 
	 * @throws NoSuchFieldException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 */
	public void travel(String shellName, Shell parentShell)
	throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchFieldException
	{
		//	默认寻找名为“main”的节点
		if("".equals(shellName))
		{
			shellName = "main";
			parentShell = null;
		}

		//	寻找shellName指定的节点
		Element elementShell = null;
		Iterator iter = rootElement.elementIterator("Shell");
		while(iter.hasNext())
		{
			Element element = (Element) iter.next();
			if(shellName.equals(element.attributeValue("name")))
			{
				elementShell = element;
				break;
			}
		}

		//	找到指定节点后，创建相应组件，并遍历子节点
		if(elementShell != null)
		{
			//	获取主窗口类信息，默认为Shell
			String shellClassName = elementShell.attributeValue("class");
			if("".endsWith(shellClassName))
			{
				shellClassName = "org.eclipse.swt.widgets.Shell";
			}

			//	获取主窗口风格信息
			String[] styles = null;
			List styleList = elementShell.elements("style");
			if(styleList != null)
			{
				int len = styleList.size();
				styles = new String[len];
				for(int i = 0; i < len; i ++)
				{
					Element e = (Element) styleList.get(i);
					styles[i] = e.attributeValue("value");
				}
			}

			//	获取父窗口信息，如果带有parent属性，就根据此属性确定父窗口信息
			SingletonGlobalInfo sgi = SingletonGlobalInfo.getInstance();
			if(parentShell == null)
			{
				String parentName = elementShell.attributeValue("parent");
				if(! "".equals(parentName))
				{
					parentShell = sgi.getShell(parentName);
				}
			}

			//	初始化组件工厂
			ShellFactory sf = null;
			if(parentShell == null)
			{
				SingletonDisplayFactory sdf = SingletonDisplayFactory.getInstance();
				Display disp = sdf.getDisplay();
				sf = new ShellFactory(disp, shellClassName, styles);
			}
			else
			{
				sf = new ShellFactory(parentShell, shellClassName, styles);
			}

			//	设置组件附加属性
			Iterator iterProp = elementShell.elementIterator("Property");
			while(iterProp.hasNext())
			{
				Element element = (Element) iterProp.next();
				String propName = element.attributeValue("name");
				WidgetPropertyParametersProxy wppp = new WidgetPropertyParametersProxy();
				Iterator itParam = element.elementIterator("parameter");
				while(itParam.hasNext())
				{
					Element e = (Element) itParam.next();
					String t = e.attributeValue("class");
					String v = e.getStringValue();
					wppp.addParameter(t, v);
				}
				sf.addProperty(propName, wppp.getWidgetProperty());
			}

			//	设置窗口监听器
			Iterator itLsnr = elementShell.elementIterator("Listener");
			while(itLsnr.hasNext())
			{
				//	创建监听器信息代理，并定义监听器类型
				WidgetListenerProxy wlp = new WidgetListenerProxy();
				Element elem = (Element) itLsnr.next();
				String lsnrType = elem.attributeValue("type");
				wlp.setListenerType(lsnrType);

				//	传递监听器使用的参数信息
				Iterator itParam = elem.elementIterator("parameter");
				while(itParam.hasNext())
				{
					Element e = (Element) itParam.next();
					String c = e.attributeValue("class");
					String v = e.getStringValue();
					wlp.addListenerParameter(c, v);
				}

				//	将监听器添加到组件
				sf.addListener(wlp.getWidgetListener());
			}

			//	创建组件
			shell = sf.newShell();

			//	添加到全局组件对象中
			sgi.putShell(shellName, shell);

			//	遍历子节点
			travelNodes(shellName, elementShell, shell);
		}
	}

	/**
	 * 遍历某节点的所有子节点，生成组件
	 * @param parentElement 要遍历的父节点对象
	 * @throws IllegalAccessException 
	 * @throws NoSuchFieldException 
	 * @throws ClassNotFoundException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws NoSuchMethodException 
	 */
	private void travelNodes(String shellName, Element parentElement, Widget parentWidget)
	throws SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
	{
		//	遍历所有子Widget节点
		Iterator it = parentElement.elementIterator("Widget");
		while(it.hasNext())
		{
			//	得到Widget子节点
			Element element = (Element) it.next();

			//	取得子节点名称和节点类名称
			String widgetName = element.attributeValue("name");
			String widgetClass = element.attributeValue("class");

			//	获取子节点界面风格信息
			String[] styles = null;
			List styleList = element.elements("style");
			if(styleList != null)
			{
				int len = styleList.size();
				styles = new String[len];
				for(int i = 0; i < len; i ++)
				{
					Element e = (Element) styleList.get(i);
					styles[i] = e.attributeValue("value");
				}
			}

			//	初始化组件工厂
			WidgetFactory wf = new WidgetFactory((Composite) parentWidget, widgetClass, styles);

			//	设置组件附加属性
			Iterator iterProp = element.elementIterator("Property");
			while(iterProp.hasNext())
			{
				Element elem = (Element) iterProp.next();
				String propName = elem.attributeValue("name");
				WidgetPropertyParametersProxy wppp = new WidgetPropertyParametersProxy();
				Iterator itParam = elem.elementIterator("parameter");
				while(itParam.hasNext())
				{
					Element e = (Element) itParam.next();
					String t = e.attributeValue("class");
					String v = e.getStringValue();
					wppp.addParameter(t, v);
				}
				wf.addProperty(propName, wppp.getWidgetProperty());
			}

			//	设置组件监听器
			Iterator itLsnr = element.elementIterator("Listener");
			while(itLsnr.hasNext())
			{
				//	创建监听器信息代理，并定义监听器类型
				WidgetListenerProxy wlp = new WidgetListenerProxy();
				Element elem = (Element) itLsnr.next();
				String lsnrType = elem.attributeValue("type");
				wlp.setListenerType(lsnrType);

				//	传递监听器使用的参数信息
				Iterator itParam = elem.elementIterator("parameter");
				while(itParam.hasNext())
				{
					Element e = (Element) itParam.next();
					String c = e.attributeValue("class");
					String v = e.getStringValue();
					wlp.addListenerParameter(c, v);
				}

				//	将监听器添加到组件
				wf.addListener(wlp.getWidgetListener());
			}

			//	创建组件
			Widget widget = wf.newWidget();

			//	添加到全局组件对象中
			SingletonGlobalInfo sgi = SingletonGlobalInfo.getInstance();
			sgi.putWidget(shellName, widgetName, widget);

			//	递归遍历子节点
			travelNodes(shellName, element, widget);
		}
	}

	/**
	 * 显示主窗口界面，并开始消息处理循环<br />
	 * 考虑此方法名称是否合理，工作机制是否合理
	 */
	public void createWindow()
	{
		//	显示主窗口
		if(shell == null)
		{
			return;
		}
		shell.open();

		//TODO 如果不是主Shell怎么办？
		//	开始消息循环
		Display disp = shell.getDisplay();
		while(! shell.isDisposed())
		{
			if(! disp.readAndDispatch())
			{
				disp.sleep();
			}
		}

		//	主窗口已关闭，释放资源
		disp.dispose();
	}
}
